﻿/*
 * @author: wizardc
 */

using System;
using System.Collections.Generic;
using Dou.Utils;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Dou.UI
{
    /// <summary>
    /// UI 对象复制器
    /// 注：不支持直接设置数据源，只能通过设置数据源数量的方式来使用
    /// </summary>
    [ExecuteAlways]
    [DisallowMultipleComponent]
    public class UIDuplicator : UIBehaviour
    {
        /// <summary>
        /// Item 创建时回调
        /// </summary>
        public event Action<GameObject, int> onItemInit;
        
        /// <summary>
        /// Item 更新时回调
        /// </summary>
        public event Action<GameObject, int> onItemUpdate;
        
        /// <summary>
        /// Item 失效时回调
        /// </summary>
        public event Action<GameObject, int> onItemDisable;
        
        /// <summary>
        /// 模板
        /// </summary>
        public GameObject template;
        
        /// <summary>
        /// 容器
        /// </summary>
        public Transform container;

        [SerializeField]
        private int _count;
        [SerializeField]
        private List<GameObject> _items = new List<GameObject>();
        [SerializeField]
        private bool _autoClone = false;

        /// <summary>
        /// 复制的数量
        /// </summary>
        public int count
        {
            set
            {
                if (_count != value)
                {
                    _count = value;
                    if (_autoClone)
                    {
                        Clone(true);
                    }
                }
            }
            get => _count;
        }

        /// <summary>
        /// 是否自动克隆
        /// </summary>
        public bool autoClone
        {
            set
            {
                if (_autoClone != value)
                {
                    _autoClone = value;
                    if (_autoClone)
                    {
                        Clone(true);
                    }
                }
            }
            get => _autoClone;
        }

        protected override void Awake()
        {
            if (template != null)
            {
                template.SetActive(false);
            }
        }

        protected override void Start()
        {
            if (_autoClone)
            {
                Clone(true);
            }
        }

        public GameObject GetItem(int index)
        {
            if (index < 0 || index >= _count)
            {
                return null;
            }
            return _items[index];
        }

        /// <summary>
        /// 根据数量克隆对象
        /// </summary>
        /// <param name="forceUpdate">是否强制抛出每个克隆对象的更新事件</param>
        public void Clone(bool forceUpdate = false)
        {
            if (template == null || container == null)
            {
                Log.Warning("没有设定模版或容器！");
                return;
            }

            // 多余的项目需要销毁
            if (_items.Count > _count)
            {
                for (var i = _items.Count - 1; i >= _count; i--)
                {
                    _items.RemoveAt(i);
                    onItemDisable?.Invoke(_items[i], i);
#if UNITY_EDITOR
                    if (Application.isPlaying)
                    {
                        GameObject.Destroy(_items[i]);
                    }
                    else
                    {
                        GameObject.DestroyImmediate(_items[i]);
                    }
#else
                    GameObject.Destroy(_items[i]);
#endif
                }
            }
            
            // 强制更新
            if (forceUpdate)
            {
                for (var i = 0; i < _items.Count; i++)
                {
                    onItemUpdate?.Invoke(_items[i], i);
                }
            }
            
            // 创建缺少的项目
            if (_count > _items.Count)
            {
                for (var i = _items.Count; i < _count; i++)
                {
                    var item = GameObject.Instantiate(template, container);
                    item.name = template.name + "(" + i + ")";
                    item.SetActive(true);
                    _items.Add(item);
                    onItemInit?.Invoke(item, i);
                    onItemUpdate?.Invoke(item, i);
                }
            }
        }

#if UNITY_EDITOR
        
        private void ClearClone()
        {
            foreach (var item in _items)
            {
                GameObject.DestroyImmediate(item);
            }
            _items.Clear();
        }

#endif
        
        protected override void OnDestroy()
        {
            for (int i = 0; i < _items.Count; i++)
            {
                var item = _items[i];
                onItemDisable?.Invoke(item, i);
                GameObject.Destroy(item);
            }
        }
    }
}
